﻿<!DOCTYPE HTML>
<html lang="zh">
<head>
<title>组件对象 - 语法 &amp; 使用 | AutoHotkey v2</title>
<meta name="description" content="The 组件对象 function wraps a value, SafeArray or COM 对象 遍历 use by the script or 遍历 passing to a COM method." />
<meta name="ahk:equiv-v1" content="commands/ComObjActive.htm" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link href="../static/theme.css" rel="stylesheet" type="text/css" />
<script src="../static/content.js" type="text/javascript"></script>
<script type="text/javascript">$(function(){0<=window.navigator.userAgent.toLowerCase().indexOf("ucbrowser")&&CaoNiMaDeUc()})</script>
</head>
<body>

<h1>组件对象</h1>

<p>包装一个值, 安全数组或 COM 对象, 以供脚本使用或传递给 COM 方法.</p>
<pre class="Syntax">组件对象 := <span class="func">组件对象</span>(VarType, Value <span class="optional">, Flags</span>)</pre>

<p><strong>高级:</strong> 装包或拆包原始 <a href="https://docs.microsoft.com/windows/desktop/api/oaidl/nn-oaidl-idispatch">IDispatch</a> 指针, 以供脚本使用.</p>
<pre class="Syntax">组件对象 := <span class="func">组件对象</span>(DispPtr)</pre>

<h2 id="Parameters">参数</h2>
<dl>

  <dt>VarType</dt>
  <dd>
    <p>类型: <a href="../Concepts.htm#numbers">整数</a></p>
    <p>表示值类型的整数. 类型列表见 <a href="ComObjType.htm#vt">组件对象类型</a>.</p>
  </dd>

  <dt>Value</dt>
  <dd>
    <p>类型: <a href="../Concepts.htm#numbers">整数</a></p>
    <p>要包装的值. 当前仅支持整数和指针值.</p>
  </dd>

  <dt>Flags</dt>
  <dd>
    <p>类型: <a href="../Concepts.htm#numbers">整数</a></p>
    <p>影响包装器对象行为的标志; 有关详情, 请参阅 <a href="ComObjFlags.htm">组件对象标志</a>.</p>
  </dd>

  <dt>DispPtr</dt>
  <dd>
    <p>类型: <a href="../Concepts.htm#numbers">整数</a></p>
    <p>原始 IDispatch 指针.</p>
  </dd>

</dl>

<h2 id="Returns">返回值</h2>
<p>类型: <a href="../Concepts.htm#objects">对象</a></p>
<p>返回包含<a href="ComObjType.htm">变体类型</a>和值或指针的包装器对象.</p>
<p>该对象有两个用途:</p>
<ol>
  <li>某些 COM 方法可能需要特定类型的值, 这些值在 AutoHotkey 中没有直接等效的值. 此函数允许在将值传递给 COM 方法时指定值的类型. 例如, <code>组件对象(0xB, -1)</code> 创建一个表示 COM 布尔值为 <em>true</em> 的对象.</li>
  <li>通过包装 COM 对象或 SafeArray, 脚本可以使用<a href="../Objects.htm#Usage_Objects">对象语法</a>更自然地与其交互. 但是, 大多数脚本不需要手动执行此操作, 因为包装对象是由 <a href="ComObjCreate.htm">组件对象创建</a>, <a href="ComObjArray.htm">组件对象数组</a> 和任何返回对象的 COM 方法自动创建的.</li>
</ol>

<h2 id="Ptr">Ptr</h2>
<p>如果一个包装器对象的 <a href="ComObjType.htm#vt"><em>VarType</em></a> 是 VT_UNKNOWN(13) 或包含 VT_BYREF(0x4000) 标志或 VT_ARRAY(0x2000) 标志, 则 <code>Ptr</code> 属性可用于检索对象, 类型化变量或安全数组的地址. 这允许将 组件对象 本身传递给任何具有 <code>"Ptr"</code> 类型的 <a href="DllCall.htm">动态库调用</a> 或 <a href="ComCall.htm">组件调用</a> 参数, 但也可以显式地使用. 例如, 在这些情况下, <code>ComObj.Ptr</code> 等同于 <code>组件对象值(ComObj)</code>.</p>
<p>如果一个包装器对象的 <a href="ComObjType.htm#vt"><em>VarType</em></a> 是 VT_UNKNOWN (13) 或 VT_DISPATCH (9) 并且包装指针为 null(0), 则可以使用 <code>Ptr</code> 属性来检索当前的 null 值, 或者为包装对象赋值一个指针. 一旦被赋值(如果非-null), 当包装对象被释放时, 指针将被自动释放. 这可以与类型为 <code>"Ptr*"</code> 或 <code>"PtrP"</code> 的 <a href="DllCall.htm">动态库调用</a> 或 <a href="ComCall.htm">组件调用</a> 输出参数一起使用, 以确保指针会被自动释放, 例如当发生错误时. 有关示例, 请参阅 <a href="ComObjQuery.htm#ExIE">组件对象查询</a>.</p>

<h2 id="ByRef">ByRef</h2>
<p>如果包装器对象的 <a href="ComObjType.htm#vt"><em>VarType</em></a> 包含 VT_BYREF(0x4000) 标志, 可用空的方括号对 <code>[]</code> 来读写引用的值.</p>
<p>当创建一个引用, <em>Value</em> 须为变量的内存地址, 或足够存储指定类型的值的缓存. 例如, 下面的代码可以用来创建一个 VBScript 函数可以写入的变量:</p>
<pre>vbuf := 创建缓冲区(24, 0)
vref := 组件对象(0x400C, vbuf.ptr)  <em>; 0x400C 是 VT_BYREF 与 VT_VARIANT 组合而得.</em>

vref[] := "in value"
sc.运行("Example", vref)  <em>; sc 应像<a href="#ExByRef">下面例子</a>一样进行初始化.</em>
信息框 vref[]</pre>

<h2 id="Remarks">备注</h2>
<p>当使用此函数包装 <a href="http://msdn.microsoft.com/en-us/library/dd318520.aspx">IDispatch</a> 或 IUnknown 接口指针时, 包装器对象负责在适当的时候自动释放指针. 如果省略 <em>VarType</em>, 则<a href="ComObjQuery.htm">查询</a>对象的 IDispatch 接口; 如果返回一个, 则立即释放 <em>DispPtr</em>. 因此, 如果脚本打算在调用这个函数后使用指针, 它必须首先调用 <code><a href="ObjAddRef.htm">增加对象引用计数</a>(DispPtr)</code>.</p>
<p>可以使用  <a href="ComObjType.htm">组件对象类型</a> 检索包装器对象的 <em>VarType</em>.</p>
<p>可以使用 <a href="ComObjValue.htm">组件对象值</a> 检索包装器对象的 <em>Value</em>.</p>
<p><b>已知限制:</b> 每次包装 COM 对象时, 都会创建新的包装器对象. 如 <code>obj1 == obj2</code> 和 <code>数组[obj1] := value</code> 这样的比较和赋值运算, 将这两个包装器对象视为唯一的, 即使它们包含相同的 COM 对象.</p>

<h2 id="Related">相关</h2>
<p><a href="ComObjCreate.htm">组件对象创建</a>, <a href="ComObjGet.htm">组件对象获取</a>, <a href="ComObjConnect.htm">组件对象连接</a>, <a href="ComObjFlags.htm">组件对象标志</a>, <a href="ObjAddRef.htm">ObjAddRef/ObjRelease</a>, <a href="ComObjQuery.htm">组件对象查询</a>, <a href="http://msdn.microsoft.com/en-us/library/ms221467.aspx">GetActiveObject (MSDN)</a></p>

<h2 id="Examples">示例</h2>
<div class="ex" id="ExByRef">
<p><a href="#ExByRef">#1</a></p>
<pre>
<em>; 条件 - ScriptControl 需 32 位版本的 AutoHotkey.</em>
code := "
(
Sub Example(Var)
    信息框 Var
    Var = "out value!"
End Sub
)"
sc := <a href="ComObjCreate.htm">组件对象创建</a>("ScriptControl"), sc.Language := "VBScript", sc.AddCode(code)


<em>; 示例: 传递 VARIANT ByRef 至 COM 函数.</em>
变量 := ComVar.new()
var[] := "in value"
sc.运行("Example", var.ref)
信息框 var[]

<em>; ComVar: 创建可用于按引用(ByRef) 传值的对象.
;   this[] 检索值.
;   this[] := Val 设置值.
;   this.ref 检索按引用传值的对象, 以传递到 COM 方法.</em>
class ComVar {
    __new(类型 := 0xC) {
        <em>; 为类型化变量分配内存.
        ; 支持的最大类型是 x64(24 字节) 上的 VT_VARIANT.</em>
    ; 处理 VARIANT 和 AutoHotkey 内部类型之间的所有转换.</em>
        this.变量 := 创建缓冲区(24, 0)
        <em>; 创建一个可以用来传递变量 ByRef 的对象.</em>
        this.ref := 组件对象(0x4000|类型, this.var.ptr + (type=0xC ? 0 : 8))
    }
    __item {
        get => this.ref[]
        set => this.ref[] := value
    }
}
</pre>
</div>

</body>
</html>